<script setup lang="ts">
import { onMounted, ref, toRaw, watch } from "vue";
import { useI18n } from "vue-i18n";
import DataChart from "@/views/dataCenter/iotdata/component/DataChart.vue";
import DataList from "@/views/dataCenter/iotdata/component/DataList.vue";
import DataRealTime from "@/views/dataCenter/iotdata/component/DataRealTime.vue";
import Searchbox from "@/views/components/searchbox/Searchbox.vue";
import {
  getTimeRecentOptions,
  getTimeTypeOptions,
  pageSizeOptions
} from "@/utils/appCommon/appCommonOptions/app";
import { useLogic } from "@/views/system/user/logic/logic";
import { getProductListApi, getProductOptionsApi } from "@/api/products/product";
import { getDeviceGroupOptionsApi } from "@/api/products/deviceGroup";
import {getDeviceOptionsApi} from "@/api/products/device";
import { handleTree } from "@/utils/tree";
import { useUserStore } from "@/store/modules/user";
import { storeToRefs } from "pinia";
import { ElMessage, ElMessageBox, ElProgress } from "element-plus";
import { ArrowDown } from "@element-plus/icons-vue";
import { getIotDataPageListApi } from "@/api/iotdata/iotdata";
import { getProductAttributes } from "@/utils/appCommon/appCommonOptions/deviceParam";
import { getDistributeTableOptionsApi } from "@/api/clusters/distributeTables";
import { useRoute } from "vue-router";
defineOptions({
  name: "iotdata"
});

const pageSizeOps = ref(pageSizeOptions)
const route = useRoute();
const storeInfo = useUserStore()
const {deptId}= storeToRefs(storeInfo)
const { t } = useI18n();
// 搜索处理 - 增加搜索参数存储
const searchParams = ref({
  deptId: deptId.value,  //初始部门id
  productId: undefined,
  productKey: undefined,
  deviceGroupId: undefined,
  deviceNos:[],
  page:1,
  pageSize:500,
  timeType: 0 ,  // 0时间段 1最近时间
  timeRange: [],
  recent: 60,
  distributeTableId: undefined,
});

const selected = ref(0);
function tabClick({ index }) {
  selected.value = index;
}
let productList = [];
const productOptions = ref([]);
const deviceGroupOptions = ref([]);
const {deptTreeList,getDeptTree}  = useLogic()
const deviceNoOptions = ref([])
const distributeTableOptions = ref([]);

const loadDistributeTableOptions = async () => {
  const { code, data } = await getDistributeTableOptionsApi(searchParams.value.deptId,'id', 'table');
  if (code === 0 && data) {
    distributeTableOptions.value = data.options;
  }
};

watch(()=>route.query,(newValue)=>{
  if (route.query.distributeTableId && Number(route.query.distributeTableId)>0) {
    searchParams.value.distributeTableId = Number(route.query.distributeTableId);
  }
  if (route.query.deptId && Number(route.query.deptId)>0) {
    searchParams.value.deptId = Number(route.query.deptId);
  }
  setTimeout(()=>{
    reloadThisPage()
  },5)
},{immediate:true,deep:true});

const reloadThisPage = async () => {
  await loadDistributeTableOptions();
  await getDeptTree()
  const productOptionsRes = await getProductListApi({
    pageSize:500,
    page:1,
    wheres:{
      openStatus:1,
    },
  })
  if(productOptionsRes.code == 0){
    productList = productOptionsRes.data.list ? productOptionsRes.data.list : [];
    productOptions.value = [
      ...productOptionsRes.data.list.map(option => ({
        val: option.id,
        label: option.name
      }))
    ];
  }
  await reLoadDeviceGroups()
}

onMounted(async () => {


})

const reLoadDeviceGroups = async ()=>{
  const req = new Map;
  if(searchParams.value.deptId){
    req.deptId = searchParams.value.deptId;
  }
  const deviceGroupOptionsRes = await getDeviceGroupOptionsApi(req)
  if(deviceGroupOptionsRes.code == 0){
    deviceGroupOptions.value = handleTree(deviceGroupOptionsRes.data.options);
    console.log(toRaw(deviceGroupOptions.value))
  }
}

const reLoadDevices = async ()=>{
  const req = {
    fieldKey:"deviceNo",
    fieldLabel:"name",
  };
  if(searchParams.value.deptId){
    req.deptId = searchParams.value.deptId;
  }
  if(searchParams.value.productId){
    req.productId = searchParams.value.productId;
  }
  if(searchParams.value.deviceGroupId){
    req.deviceGroupId = searchParams.value.deviceGroupId;
  }
  deviceNoOptions.value = [];
  const deviceOptionsRes = await getDeviceOptionsApi(req)
  if(deviceOptionsRes.code == 0){
    deviceNoOptions.value = deviceOptionsRes.data.options;
  }
}

const timeTypeOptions = ref(getTimeTypeOptions());
const recentOptions = ref(getTimeRecentOptions())

const listComponents = [
  {
    key: "DataList",
    title: t('datacenter.iotdataPage.listData'),
    component: DataList
  },
  {
    key: "DataChart",
    title: t('datacenter.iotdataPage.chartData'),
    component: DataChart
  },
  {
    key: "DataRealTime",
    title: t('datacenter.iotdataPage.realTimeData'),
    component: DataRealTime
  }
];

const searchFields = ref([
  {
    prop: "productId",
    name: t('datacenter.iotdataPage.product'),
    type: "select",
    clearable: false,
    isHidden: false,
    formOptions: productOptions
  },
  {
    prop: "deviceNos",
    name: t('datacenter.iotdataPage.deviceNo'),
    type: "multiSelect",
    clearable: true,
    isHidden: false,
    formOptions: deviceNoOptions
  },
  {
    prop: "timeType",
    name: t('datacenter.iotdataPage.timeType'),
    type: "select",
    clearable: false,
    isHidden: false,
    formOptions: timeTypeOptions
  },
  {
    prop: 'timeRange',
    name: t('datacenter.iotdataPage.timeRange'),
    type: 'datetimeRange',
    clearable: true,
    isHidden: false,
  },
  {
    prop: 'recent',
    name: t('datacenter.iotdataPage.recentTime'),
    type: 'select',
    formOptions: recentOptions,
    clearable: true,
    isHidden: true,
  },
  {
    prop: 'deviceGroupId',
    name: t('datacenter.iotdataPage.deviceGroup'),
    type: 'cascader',
    cascaderOptions: deviceGroupOptions,
    clearable: true,
    isHidden: false,
    ops: {
      valueField: 'id',
      labelField: 'name',
      emitPath: false,
      checkStrictly: true
    }
  },
  {
    prop: 'deptId',
    name: t('datacenter.iotdataPage.dept'),
    type: 'cascader',
    cascaderOptions: deptTreeList,
    clearable: true,
    isHidden: false,
    ops: {
      valueField: 'id',
      labelField: 'name',
      emitPath: false,
      checkStrictly: true
    }
  },
  {
    prop: 'distributeTableId',
    name: t('datacenter.iotdataPage.distributeTable'),
    type: 'select',
    clearable: true,
    isHidden: false,
    formOptions: distributeTableOptions
  },
])

const handleChange = (e: any) => {
  console.log(e)
  if(e.productId != searchParams.value.productId){
    searchParams.value.productId = e.productId
    searchParams.value.deviceNos = []
    searchParams.value.productKey = productList.find(item => item.id === e.productId)?.productKey || '';
    reLoadDevices()
  }
  if(e.deptId != searchParams.value.deptId){
    searchParams.value.deptId = e.deptId
    reLoadDeviceGroups()
    reLoadDevices()
  }
  if(e.deviceGroupId != searchParams.value.deviceGroupId){
    searchParams.value.deviceGroupId = e.deviceGroupId
    reLoadDevices()
  }
  if(e.timeType == 0){
    searchFields.value.map((item,index) => {
      if(item.prop == "timeRange"){
        searchFields.value[index].isHidden = false
      }
      if(item.prop == "recent"){
        searchFields.value[index].isHidden = true
      }
    })
  }else{
    searchFields.value.map((item,index) => {
      if(item.prop == "timeRange"){
        searchFields.value[index].isHidden = true
      }
      if(item.prop == "recent"){
        searchFields.value[index].isHidden = false
      }
    })
  }
}

const total = ref(0)
const iotData = ref([])
const iotColumnOptions = ref([])

const handleSearch = async (e:any) => {
  searchParams.value.page = 1
  console.log(e)
  Object.keys(e).forEach(key => {
    searchParams.value[key] = e[key];
  });
  searchParams.value.productKey = productList.find(item => item.id === searchParams.value.productId)?.productKey || '';

  console.log(toRaw(searchParams.value))
  const checkres = checkSearchValid()
  if(!checkres){
    return
  }
  generateIotColumns()
  console.log(toRaw(iotColumnOptions.value))
  await loadRealData()
}

const generateIotColumns = () => {
  iotColumnOptions.value = getProductAttributes(searchParams.value.productKey)
}

const onPageChange = async (e:any) => {
  searchParams.value.page = e.page
  searchParams.value.pageSize = e.pageSize
  await loadRealData()
}

// 替换原有模拟数据逻辑
const loadRealData = async () => {
  try {
    const req = toRaw(searchParams.value)
    iotData.value = []
    total.value = 0
    console.log(req)
    const { code,data } = await getIotDataPageListApi(req);
    if (code == 0 && data) {
      iotData.value = data.list ? data.list : [];
      total.value = data.total;
    }
  } catch (error) {
    console.error('数据加载失败:', error);
  }
};

const checkSearchValid = ()=>{
  if(!searchParams.value.productId){   //保证必须只有一种产品
      ElMessage.error(t('datacenter.iotdataPage.productRequired'));
      return false;
  }
  if(!searchParams.value.deviceNos || searchParams.value.deviceNos.length==0){
    ElMessage.error(t('datacenter.iotdataPage.deviceRequired'));
    return false;
  }

  if((!searchParams.value.timeType || searchParams.value.timeType==0) &&
    (!searchParams.value.timeRange || searchParams.value.timeRange.length==0)){
    ElMessage.error(t('datacenter.iotdataPage.timeRangeRequired'));
    return false;
  }

  if((searchParams.value.timeType || searchParams.value.timeType==1) &&
    (!searchParams.value.recent || searchParams.value.recent< 1)){
    ElMessage.error(t('datacenter.iotdataPage.recentTimeRequired'));
    return false;
  }

  return true;
}

const handleReset = (e:any) => {
}

// 分页变化处理
const handleSizeChange = (pageSize: number) => {
  searchParams.value.pageSize = pageSize;
};
const handleCurrentChange = (currentPage: number) => {
  searchParams.value.page = currentPage;
};

// 下载相关状态
const downloadLoading = ref(false);
const cancelDownload = ref(false);
const downloadProgress = ref(0);
const downloadDialogVisible = ref(false);
const downloadProgressMsg = ref('');
const allDownloadedData = ref([]);

// 处理下载命令
const handleDownloadCommand = (command: string) => {
  if (command === 'current') {
    downloadCurrentPage();
  } else if (command === 'all') {
    downloadAllData();
  }
};

// 下载当前页面数据
const downloadCurrentPage = async () => {
  try {
    // 直接使用当前已加载的数据
    if (iotData.value.length === 0) {
      ElMessage.warning(t('datacenter.iotdataPage.currentPageNoData'));
      return;
    }

    // 从iotColumnOptions.value中提取val字段作为表头
    const csvHeaders = iotColumnOptions.value.map(column => column.val);
    // 导出CSV
    exportToCSV(iotData.value, 'iotdata_current_page', csvHeaders);
  } catch (error) {
    console.error('下载失败:', error);
    ElMessage.error(t('datacenter.iotdataPage.downloadFailed'));
  }
};

// 下载全部数据
const downloadAllData = async () => {
  try {
    // 检查搜索参数
    const checkres = checkSearchValid();
    if (!checkres) {
      return;
    }

    // 重置下载状态
    cancelDownload.value = false;
    downloadProgress.value = 0;
    downloadDialogVisible.value = true;
    downloadProgressMsg.value = '准备下载...';
    allDownloadedData.value = [];

    // 从第1页开始，每页10000条
    let currentPage = 1;
    const pageSize = 10000;
    let totalPages = 1;
    let totalRecords = 0;

    // 获取总记录数 - 先深拷贝searchParams
    const totalReq = JSON.parse(JSON.stringify(toRaw(searchParams.value)));
    totalReq.page = 1;
    totalReq.pageSize = 1;
    const totalRes = await getIotDataPageListApi(totalReq);

    if (totalRes.code === 0 && totalRes.data) {
      totalRecords = totalRes.data.total || 0;
      totalPages = Math.ceil(totalRecords / pageSize);

      if (totalRecords === 0) {
        downloadDialogVisible.value = false;
        ElMessage.warning(t('datacenter.iotdataPage.noDataFound'));
        return;
      }

      // 逐页获取数据
      while (currentPage <= totalPages && !cancelDownload.value) {
        downloadProgressMsg.value = t('datacenter.iotdataPage.downloadingPage', { current: currentPage, total: totalPages });

        // 深拷贝searchParams，然后设置分页参数
        const req = JSON.parse(JSON.stringify(toRaw(searchParams.value)));
        req.page = currentPage;
        req.pageSize = pageSize;

        const { code, data } = await getIotDataPageListApi(req);

        if (cancelDownload.value) break;

        if (code === 0 && data && data.list) {
          allDownloadedData.value = [...allDownloadedData.value, ...data.list];

          // 更新进度
          downloadProgress.value = Math.round((currentPage / totalPages) * 100);

          // 避免请求过快
          await new Promise(resolve => setTimeout(resolve, 100));
        } else {
          throw new Error('获取数据失败');
        }

        currentPage++;
      }

      // 关闭对话框
      downloadDialogVisible.value = false;

      // 如果取消了下载，也要导出已获取的数据
      if (allDownloadedData.value.length > 0) {
        // 从iotColumnOptions.value中提取val字段作为表头
        const csvHeaders = iotColumnOptions.value.map(column => column.val);
        exportToCSV(allDownloadedData.value, 'iotdata_all', csvHeaders);
      }

      if (cancelDownload.value) {
        ElMessage.info(t('datacenter.iotdataPage.downloadCanceled', { count: allDownloadedData.value.length }));
      } else {
        ElMessage.success(t('datacenter.iotdataPage.downloadComplete', { count: allDownloadedData.value.length }));
      }
    }
  } catch (error) {
    console.error('下载失败:', error);
    downloadDialogVisible.value = false;

    // 即使出错，也要导出已获取的数据
    if (allDownloadedData.value.length > 0) {
        // 从iotColumnOptions.value中提取val字段作为表头
        const csvHeaders = iotColumnOptions.value.map(column => column.val);
        exportToCSV(allDownloadedData.value, 'iotdata_partial', csvHeaders);
      ElMessage.warning(t('datacenter.iotdataPage.downloadError', { count: allDownloadedData.value.length }));
    } else {
      ElMessage.error(t('datacenter.iotdataPage.downloadFailed'));
    }
  }
};

// 取消下载
const handleCancelDownload = () => {
  ElMessageBox.confirm(t('datacenter.iotdataPage.confirmCancelDownload'), t('datacenter.iotdataPage.cancelDownload'), {
    confirmButtonText: t('datacenter.iotdataPage.confirm'),
    cancelButtonText: t('datacenter.iotdataPage.cancel'),
    type: 'warning'
  }).then(() => {
    cancelDownload.value = true;
  }).catch(() => {
    // 取消操作
  });
};

// 导出CSV文件
  const exportToCSV = (data: any[], filename: string, headers?: string[]) => {
    if (!data || data.length === 0) {
      return;
    }

    // 获取所有列名
    const csvHeaders = headers || Object.keys(data[0]);

    // 构建CSV内容
    let csvContent = '\uFEFF'; // BOM，确保Excel正确识别UTF-8

    // 添加表头
    csvContent += csvHeaders.map(header => {
      // 替换逗号和换行符
      return `"${header.replace(/"/g, '""')}"`;
    }).join(',') + '\n';

    // 添加数据行
      data.forEach(row => {
        csvContent += csvHeaders.map(header => {
          const value = row[header] !== null && row[header] !== undefined ? String(row[header]) : '';
          // 替换逗号和换行符，并添加引号
          return `"${value.replace(/"/g, '""')}"`;
        }).join(',') + '\n';
      });

    // 生成时间戳：年月日时分秒
    const now = new Date();
    const timestamp = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}`;

    // 创建下载链接
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement('a');

    if (link.download !== undefined) {
      const url = URL.createObjectURL(blob);
      link.setAttribute('href', url);
      link.setAttribute('download', `${filename}_${timestamp}.csv`);
      link.style.visibility = 'hidden';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(url);
    }
  };
</script>

<template>
  <el-card shadow="never">
    <template #header>
      <div class="card-header">
        <Searchbox
        :fields= searchFields
        :initialValues="searchParams"
        :maxVisibleFields=5
        @change="handleChange"
        @search="handleSearch"
        @reset="handleReset"
        />
        <div style="margin-top: 5px;">
          <el-dropdown @command="handleDownloadCommand" :disabled="downloadLoading">
            <el-button type="primary" size="small">
              {{ t('datacenter.iotdataPage.downloadData') }}
              <el-icon class="el-icon--right">
                <arrow-down />
              </el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="current">{{ t('datacenter.iotdataPage.downloadCurrentPage') }}</el-dropdown-item>
                <el-dropdown-item command="all">{{ t('datacenter.iotdataPage.downloadAllData') }}</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>

        <!-- 下载进度对话框 -->
        <el-dialog
          v-model="downloadDialogVisible"
          title="{{ t('datacenter.iotdataPage.downloadProgress') }}"
          width="400px"
          :close-on-click-modal="false"
          :close-on-press-escape="false"
          :show-close="false"
        >
          <div class="text-center py-4">
            <p class="mb-4">{{ downloadProgressMsg }}</p>
            <el-progress :percentage="downloadProgress" :status="cancelDownload ? 'exception' : 'success'" />
            <p class="mt-4 text-gray-500">{{ t('datacenter.iotdataPage.downloadedCount', { count: allDownloadedData.length }) }}</p>
          </div>
          <template #footer>
            <div class="text-center">
              <el-button @click="handleCancelDownload" :loading="downloadLoading">{{ t('datacenter.iotdataPage.cancelDownload') }}</el-button>
            </div>
          </template>
        </el-dialog>
      </div>
    </template>

    <el-tabs @tab-click="tabClick">
      <template v-for="(item, index) of listComponents" :key="item.key">
        <el-tab-pane :lazy="true">
          <template #label>
            <span
              v-tippy="{
                maxWidth: 'none',
                content: `${item.title}`
              }"
            >
              {{ item.title }}
            </span>
          </template>
          <keep-alive>
            <div>
              <component :is="item.component"
                         :key="item.key"
                         v-show="selected == index"
                         :params="searchParams"
                         :columns="iotColumnOptions"
                         :data="iotData"
                         :total="total"
                         @onPageChange="onPageChange"
                         :deviceOptions="deviceNoOptions"
              />
              <!-- 分页组件 -->
              <div class="pagination-container" v-if="selected==0 || selected==1">
                <el-pagination
                  v-model:current-page="searchParams.page"
                  v-model:page-size="searchParams.pageSize"
                  :page-sizes="pageSizeOps"
                  :total="total"
                  layout="total, sizes, prev, pager, next, jumper"
                  @size-change="handleSizeChange"
                  @current-change="handleCurrentChange"
                />
              </div>
            </div>
          </keep-alive>
        </el-tab-pane>
      </template>
    </el-tabs>

  </el-card>
</template>

<style scoped lang="scss">
.pagination-container {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}
</style>
